/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.app.service.impl;

import com.yanlight.Constants;
import com.yanlight.app.dal.dao.*;
import com.yanlight.app.dal.dto.CompanyQuery;
import com.yanlight.app.dal.entity.*;
import com.yanlight.app.model.CompanySpec;
import com.yanlight.app.model.PayCodeSpec;
import com.yanlight.app.request.CompanyAddRequest;
import com.yanlight.app.request.CompanyModifyRequest;
import com.yanlight.app.request.CompanyQueryRequest;
import com.yanlight.app.response.CompanyAddResponse;
import com.yanlight.app.response.CompanyDetailResponse;
import com.yanlight.app.response.CompanyListResponse;
import com.yanlight.app.service.AliOssService;
import com.yanlight.app.service.CompanyService;
import com.yanlight.exception.ErrorType;
import com.yanlight.exception.TradeException;
import com.yanlight.type.CompanyType;
import com.yanlight.type.ReviewType;
import com.yanlight.type.StatusType;
import com.yanlight.type.UserRootRole;
import com.yanlight.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author haolw
 * @time 2017/07/18
 */
@Service
public class CompanyServiceImpl implements CompanyService {
    private static final String COMPANY_KEY = "trade_company_";
    @Autowired
    private CompanyDAO companyDAO;
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private GroupRoleDAO groupRoleDAO;
    @Autowired
    private PaycodeDAO paycodeDAO;
    @Autowired
    private WxpayConfigDAO wxpayConfigDAO;
    @Autowired
    private AlipayConfigDAO alipayConfigDAO;

    @Override
    public boolean checkAvailable(Integer companyId) {
        Company company = companyDAO.findById(companyId);
        if (company == null) {
            return false;
        }
        Integer status = company.getStatus();
        if (status.equals(StatusType.UNACTIVITY.ordinal())) {
            return false;
        }
        return true;
    }

    @Override
    public boolean exist(Integer companyId) {
        Company company = companyDAO.findById(companyId);
        if (company == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public CompanyDetailResponse findById(Integer id) {
        CompanyDetailResponse response = new CompanyDetailResponse();
        Company company = companyDAO.findById(id);
        if (company == null) {
            throw TradeException.error(ErrorType.NOT_EXIST_RECORD);
        }
        BeanUtils.copyProperties(company, response);
        response.setLogo(ToolsUtil.wrapImage(company.getLogo()));
        WxpayConfig wxpayConfig = wxpayConfigDAO.findByCompanyId(id);
        if (wxpayConfig != null) {
            response.setWxpayStatus(wxpayConfig.getStatus());
        }
        AlipayConfig alipayConfig = alipayConfigDAO.findByCompanyId(id);
        if (alipayConfig != null) {
            response.setAlipayStatus(alipayConfig.getStatus());
        }
        List<PayCode> paycodes = paycodeDAO.findByCompanyId(id);
        PayCodeSpec spec;
        for (PayCode payCode : paycodes) {
            spec = new PayCodeSpec();
            BeanUtils.copyProperties(payCode, spec);
            spec.setQrCode(ToolsUtil.encryptPaycode(payCode.getValue()));
            response.addPaycodeSpec(spec);
        }
        return response;
    }

    @Override
    public CompanyListResponse findList(CompanyQueryRequest request) {
        CompanyListResponse response = new CompanyListResponse();
        CompanyQuery condition = new CompanyQuery();
        BeanUtils.copyProperties(request, condition);
        int count = companyDAO.count(condition);
        if (count > 0) {
            List<Company> companys = companyDAO.findList(condition);
            List<Integer> companyIds = new ArrayList<Integer>(8);
            for (Company item : companys) {
                companyIds.add(item.getId());
            }

            List<WxpayConfig> wxpayConfigs = wxpayConfigDAO.findByCompanyIds(companyIds);
            Map<Integer, WxpayConfig> wxpayConfigMap = new HashMap<Integer, WxpayConfig>(8);
            for (WxpayConfig wxpayConfig : wxpayConfigs) {
                wxpayConfigMap.put(wxpayConfig.getCompanyId(), wxpayConfig);
            }

            List<AlipayConfig> alipayConfigs = alipayConfigDAO.findByCompanyIds(companyIds);
            Map<Integer, AlipayConfig> alipayConfigMap = new HashMap<Integer, AlipayConfig>(8);
            for (AlipayConfig alipayConfig : alipayConfigs) {
                alipayConfigMap.put(alipayConfig.getCompanyId(), alipayConfig);
            }

            CompanySpec spec;
            for (Company item : companys) {
                Integer companyId = item.getId();
                spec = new CompanySpec();
                BeanUtils.copyProperties(item, spec);
                spec.setLogo(ToolsUtil.wrapImage(item.getLogo()));
                WxpayConfig wxpayConfig = wxpayConfigMap.get(companyId);
                if (wxpayConfig != null) {
                    spec.setWxpayStatus(wxpayConfig.getStatus());
                }
                AlipayConfig alipayConfig = alipayConfigMap.get(companyId);
                if (alipayConfig != null) {
                    spec.setAlipayStatus(alipayConfig.getStatus());
                }
                response.addCompany(spec);
            }
        }
        response.setPageSize(request.getPageSize());
        response.setTotalRecord(count);
        return response;
    }

    private String fileUpload(MultipartFile file) {
        String fileType = null;

        String oldFile = file.getOriginalFilename();
        if (!StringUtils.isEmpty(oldFile)) {
            String[] nameArray = oldFile.split("\\.");
            if (nameArray.length > 1) {
                fileType = nameArray[nameArray.length - 1];
            }
        }

        String fileName = UUIDUtils.random();
        String imageUrl = null;
        String allName = fileName + "." + fileType;
        try {
            imageUrl = AliOssService.fileupload(file.getInputStream(), allName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageUrl;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CompanyAddResponse add(CompanyAddRequest request) {

        CompanyAddResponse response = new CompanyAddResponse();
        String phone = request.getPhone();
        String email = request.getEmail();
        String mchId = request.getMchId();
        String mchUserId = request.getMchUserId();
        String password = request.getPassword();
        MultipartFile logoFile = request.getLogo();
        Company company = companyDAO.findByPhone(phone);
        if (company != null) {
            throw TradeException.error(ErrorType.REGISTERED_PHONE);
        }
        company = companyDAO.findByEmail(email);
        if (company != null) {
            throw TradeException.error(ErrorType.REGISTERED_EMAIL);
        }
        if (StringUtils.isBlank(password)) {
            password = Constants.INITIALIZE_PASSWORD;
        }
        password = EncryptUtil.md5AndSalt(password);
        String nowTime = DateTimeUtil.getNowTime();
        company = new Company();
        company.setName(request.getName());
        company.setShortName(request.getShortName());
        company.setPhone(phone);
        company.setEmail(email);
        company.setAddress(request.getAddress());
        company.setType(CompanyType.MERCHANT.ordinal());
        company.setReviewType(ReviewType.REVIEWED.ordinal());
        company.setStatus(request.getStatus());
        company.setCreateTime(nowTime);
        company.setExpireTime(DateTimeUtil.plusMonth(request.getExpireMonth()));
        if (logoFile != null) {
            String logoPath = fileUpload(logoFile);
            company.setLogo(logoPath);
        } else {
            company.setLogo("");
        }

        companyDAO.save(company);
        Integer companyId = company.getId();
        GroupRole groupRole = new GroupRole();
        groupRole.setCompanyId(companyId);
        groupRole.setName(company.getName());
        groupRole.setExtId(1);
        groupRoleDAO.save(groupRole);
        Admin admin = new Admin();
        admin.setPhone(phone);
        admin.setEmail(email);
        admin.setPassword(password);
        admin.setStatus(StatusType.ACTIVITY.ordinal());
        admin.setCreateTime(nowTime);
        admin.setCompanyId(companyId);
        admin.setRoleId(groupRole.getId());
        admin.setRoot(UserRootRole.PARTNER_ADMIN.getType());
        userDAO.save(admin);

        //新增商户时不再自动生成聚合码
//        PayCode paycode = new PayCode();
//        paycode.setCompanyId(companyId);
//        paycode.setStatus(StatusType.ACTIVITY.ordinal());
//        paycode.setValue(EncryptUtil.md5_16(ToolsUtil.uuid()));
//        paycode.setCreateTime(nowTime);
//        paycodeDAO.save(paycode);
        
        if (StringUtils.isNotBlank(mchId)) {
            WxpayConfig wxConfig = new WxpayConfig();
            wxConfig.setCompanyId(companyId);
            wxConfig.setMchId(mchId);
            wxConfig.setCreateTime(nowTime);
            wxpayConfigDAO.save(wxConfig);
        }
        if (StringUtils.isNotBlank(mchUserId)) {
            AlipayConfig alipayConfig = new AlipayConfig();
            alipayConfig.setCompanyId(companyId);
            alipayConfig.setMchUserId(mchUserId);
            alipayConfig.setCreateTime(nowTime);
            alipayConfigDAO.save(alipayConfig);
            response.setAlipayPid(mchUserId);
        }
        String key = getCompanyKey(company.getId());
        JedisUtil.set(key, company);
        response.setId(company.getId());
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id) {
        companyDAO.deleteById(id);
        groupRoleDAO.deleteByCompanyId(id);
        userDAO.deleteByCompanyId(id);
        paycodeDAO.deleteByCompanyId(id);
        wxpayConfigDAO.deleteByCompanyId(id);
        alipayConfigDAO.deleteByCompanyId(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyStatus(Integer id, Integer status) {
        Company company = companyDAO.findById(id);
        if (company != null) {
            companyDAO.modifyStatus(id, status);
            String key = getCompanyKey(id);
            if (status.equals(StatusType.ACTIVITY.ordinal())) {
                company.setStatus(StatusType.ACTIVITY.ordinal());
            } else {
                company.setStatus(StatusType.UNACTIVITY.ordinal());
            }
            JedisUtil.set(key, company);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modify(CompanyModifyRequest request) {
        Integer id = request.getId();
        Company company = companyDAO.findById(id);
        if (company != null) {
            String phone = request.getPhone();
            String email = request.getEmail();
            Integer status = request.getStatus();
            MultipartFile logoFile = request.getLogo();
            if (!company.getPhone().equals(phone)) {
                Company cheakCompany = companyDAO.findByPhone(phone);
                if (cheakCompany != null) {
                    throw TradeException.error(ErrorType.REGISTERED_PHONE);
                }
            }
            if (!company.getEmail().equals(email)) {
                Company cheakCompany = companyDAO.findByEmail(email);
                if (cheakCompany != null) {
                    throw TradeException.error(ErrorType.REGISTERED_EMAIL);
                }
            }
            company.setName(request.getName());
            company.setShortName(request.getShortName());
            company.setPhone(request.getPhone());
            company.setEmail(request.getEmail());
            company.setStatus(status);
            company.setAddress(request.getAddress());
            Integer expireMonth = request.getExpireMonth();
            if (expireMonth != null) {
                String expireTime = company.getExpireTime();
                if (DateTimeUtil.checkExpire(expireTime)) {
                    expireTime = DateTimeUtil.plusMonth(expireMonth);
                } else {
                    expireTime = DateTimeUtil.plusMonth(expireTime, expireMonth);
                }
                company.setExpireTime(expireTime);
            }
            if (logoFile != null) {
                String logoPath = FileUploadUtil.processLogo(logoFile);
                company.setLogo(logoPath);
            }
            companyDAO.update(company);
            String key = getCompanyKey(id);
            JedisUtil.set(key, company);
        }
    }

    @Override
    public void addPaycode(Integer id) {
        PayCode paycode = new PayCode();
        paycode.setCompanyId(id);
        paycode.setStatus(StatusType.ACTIVITY.ordinal());
        paycode.setValue(EncryptUtil.md5_16(ToolsUtil.uuid()));
        paycode.setCreateTime(DateTimeUtil.getNowTime());
        paycodeDAO.save(paycode);
    }


    private String getCompanyKey(Integer companyId) {
        return COMPANY_KEY + companyId;
    }

}
